package com.smart.manager.product.repository;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import com.alibaba.fastjson2.JSONObject;
import com.smart.common.entities.constant.ArcoTips;
import com.smart.common.entities.core.Page;
import com.smart.common.entities.option.SelectOption;
import com.smart.manager.member.entities.models.query.QMemberMaterialPig;
import com.smart.manager.product.entities.body.RBasicPigsty;
import com.smart.manager.product.entities.enums.CameraDirection;
import com.smart.manager.product.entities.enums.CameraStatus;
import com.smart.manager.product.entities.enums.PigstyKind;
import com.smart.manager.product.entities.enums.PigstyStatus;
import com.smart.manager.product.entities.models.BasicCamera;
import com.smart.manager.product.entities.models.BasicCameraDetail;
import com.smart.manager.product.entities.models.BasicPigsty;
import com.smart.manager.product.entities.models.query.QBasicCamera;
import com.smart.manager.product.entities.models.query.QBasicCameraDetail;
import com.smart.manager.product.entities.models.query.QBasicPigsty;
import com.smart.manager.system.repository.ConfigRepository;
import io.ebean.DB;
import io.ebean.SqlRow;
import io.ebean.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 游戏管理  猪圈管理
 *
 * @author leo
 * @date 2023/09/05
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class BasicPigstyRepository {

    private final ConfigRepository configRepository;

    public Page<BasicPigsty> pageList(RBasicPigsty.SearchBody search) {
        QBasicPigsty query = new QBasicPigsty();
        Opt.ofBlankAble(search.getCode()).ifPresent(x -> query.code.contains(x));
        Opt.ofBlankAble(search.getKind()).ifPresent(x -> query.kind.eq(x));
        Opt.ofBlankAble(search.getStatus()).ifPresent(x -> query.status.eq(x));
        Opt.ofBlankAble(search.getPlaceCode()).ifPresent(x -> query.place.code.eq(x));
        query.order().sort.asc();
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<BasicPigsty>().load(query.findPagedList());
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(RBasicPigsty.EditBody body) {
        QBasicPigsty query = new QBasicPigsty();
        BasicPigsty record = query.code.eq(body.getCode()).setMaxRows(1).findOne();
        Assert.isNull(record, "创建失败:, 猪圈代码已存在");
        //设置摄像头状态
        if (CollUtil.isNotEmpty(body.getCameraCode())) {
            List<BasicCameraDetail> details = new QBasicCameraDetail().passageId.in(body.getCameraCode()).findList();
            details.forEach(x -> x.setCameraStatus(CameraStatus.BOUND).update());
        }
        BeanUtil.copyProperties(body, BasicPigsty.class).setStatus(PigstyStatus.NULL).insert();
    }


    public void update(Long id, RBasicPigsty.EditBody body) {
        QBasicPigsty query = new QBasicPigsty();
        BasicPigsty record = query.id.eq(id).setMaxRows(1).findOne();
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        BeanUtil.copyProperties(body, record);
        if (CollUtil.isNotEmpty(body.getCameraCode())) {
            List<BasicCameraDetail> details = new QBasicCameraDetail().passageId.in(body.getCameraCode()).findList();
            CollUtil.sort(details, Comparator.comparing(BasicCameraDetail::getCameraDirection, (direction1, direction2) -> {
                if (direction1.equals(CameraDirection.FORMER)) {
                    return -1; // 如果direction1等于"前摄像头"，则排在前面
                } else if (direction2.equals(CameraDirection.FORMER)) {
                    return 1; // 如果direction2等于"前摄像头"，则排在前面
                } else {
                    return 0; // 其他情况不变
                }
            }));
            details.forEach(x -> x.setCameraStatus(CameraStatus.BOUND).update());
        }
        Objects.requireNonNull(record).update();
    }


    public void initialize(Long id) {
        QBasicPigsty query = new QBasicPigsty();
        BasicPigsty record = query.id.eq(id).setMaxRows(1).findOne();
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
//        int count = new QMemberMaterialPig().pigsty.code.eq(record.getCode()).findCount();
//        Assert.isFalse(count > 0, "当前猪圈已被入圈无法初始化");
        List<BasicCameraDetail> details = new QBasicCameraDetail().passageId.in(record.getCameraCode()).findList();
        List<BasicCameraDetail> collect = details.stream().map(x -> x.setCameraStatus(CameraStatus.NOT_BOUND)).collect(Collectors.toList());
        for (BasicCameraDetail detail : collect) {
            detail.setCameraStatus(CameraStatus.NOT_BOUND).update();
        }
        record.setCameraCode(new ArrayList<>()).update();
    }

    public int delByIds(List<Long> ids) {
        List<BasicPigsty> list = new QBasicPigsty().id.in(ids).findList();
        Assert.notEmpty(list, ArcoTips.DELETE_NOT_FOUND);
        for (BasicPigsty item : list) {
            int count = new QMemberMaterialPig().pigsty.code.eq(item.getCode()).findCount();
            Assert.isFalse(count > 0, "当前猪圈 还有猪猪不能删除!");
            List<BasicCamera> cameras = new QBasicCamera().deviceSerial.in(item.getCameraCode()).findList();
            for (BasicCamera camera : cameras) {
                camera.setCameraStatus(CameraStatus.NOT_BOUND).update();
            }
        }
        return DB.deleteAll(list);


    }


    /**
     * 获取数据字典下拉选项
     *
     * @return {@code List<SelectOption>}
     */
    public List<SelectOption> getOptions() {
        QBasicPigsty place = new QBasicPigsty();
        return place.findStream()
                .map(x -> new SelectOption().setLabel(x.getName()).setValue(x.getCode()).setDisabled(false))
                .collect(Collectors.toList());
    }

    /**
     * 获取数据字典下拉选项
     *
     * @return {@code List<SelectOption>}
     */
    public List<SelectOption> getUseOptions() {
        List<String> pigs = new QMemberMaterialPig().pigsty.kind.eq(PigstyKind.ALONE).pigsty.isNotNull().select(QMemberMaterialPig.Alias.pigsty.code).findSingleAttributeList();
        QBasicPigsty place = new QBasicPigsty();
        return place.code.notIn(pigs).cameraCode.isNotEmpty().findStream()
                .map(x -> new SelectOption().setLabel(x.getName()).setValue(x.getCode()).setDisabled(false))
                .collect(Collectors.toList());
    }



    public List<SelectOption> getCircleOptions(Boolean isOrganic) {
        JSONObject pigsty1 = configRepository.readCache("Pigsty");
        Integer accommodate = pigsty1.getInteger("accommodate");
        String sql = "SELECT pig.pigsty AS pigsty, COUNT(pig.pigsty) AS count FROM member_material_pig AS pig WHERE pig.pigsty IS NOT NULL GROUP BY pig.pigsty; ";
        List<SqlRow> sqlRows = DB.sqlQuery(sql).findList();
        List<String> pigsty = sqlRows.stream().filter(x -> x.getInteger("count") >= accommodate).map(x -> x.getString("pigsty")).collect(Collectors.toList());
        QBasicPigsty place = new QBasicPigsty();
        return place.code.notIn(pigsty).isOrganic.eq(isOrganic).cameraCode.isNotEmpty().findStream()
                .map(x -> new SelectOption().setLabel(x.getName()).setValue(x.getCode()).setDisabled(false))
                .collect(Collectors.toList());
    }


    public List<SelectOption> getCircleListOptions(Boolean isOrganic) {
        String sql = "SELECT p.\"code\", p.\"name\", COUNT(m.\"id\") AS \"total_pigs\", p.\"number\" AS \"pigsty_capacity\"\n" +
                "FROM \"public\".\"product_basic_pigsty\" p\n" +
                "LEFT JOIN \"public\".\"member_material_pig\" m ON p.\"code\" = m.\"pigsty\" AND m.\"deleted\" = false\n" +
                "WHERE p.\"deleted\" = false\n" +
                "GROUP BY p.\"code\", p.\"number\", p.\"name\"\n" +
                "HAVING COUNT(m.\"id\") < p.\"number\";";
        List<SqlRow> sqlRows = DB.sqlQuery(sql).findList();
        return sqlRows.stream().map(x->new SelectOption().setLabel(x.getString("name")).setValue(x.getString("code")).setDisabled(false))
                .collect(Collectors.toList());
    }
}






